package com.gw.vip.center.zib;

import com.alibaba.fastjson.JSONObject;
import com.gw.vip.center.bo.redis.RandomCodeInfo;
import com.gw.vip.center.constant.SysArgKey;
import com.gw.vip.center.constant.VipCenterConstants;
import com.gw.vip.center.constant.message.VipMessageKey;
import com.gw.vip.center.dto.AuthCodeDto;
import com.gw.vip.center.dto.RandomCodeDto;
import com.gw.vip.center.dto.UserInfoByCodeDto;
import com.gw.vip.center.dto.message.MessageDto;
import com.gw.vip.center.feign.VipMessageFeignClient;
import com.gw.vip.center.jwt.TokenInfo;
import com.gw.vip.center.po.UserInfo;
import com.gw.vip.center.service.dao_service.SysArgService;
import com.gw.vip.center.service.dao_service.UserInfoService;
import com.gw.vip.center.util.HttpServletUtil;
import com.gw.vip.center.util.RedisUtil;
import com.gw.vip.center.vo.AuthCodeVo;
import com.gw.vip.center.vo.RandomCodeVo;
import com.gw.vip.center.vo.UserInfoByCodeVo;
import com.gw.vip.common.exception.ExceptionEnums;
import com.gw.vip.common.exception.ServiceException;
import com.gw.vip.common.util.Snowflake;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author GW
 * @description
 * @since 2022-04-17
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class AuthBiz {

    private final VipMessageFeignClient vipMessageFeignClient;
    private final Random random;
    private final RedisUtil redisUtil;
    private final SysArgService sysArgService;
    private final Snowflake snowflake;
    private final UserInfoService userInfoService;

    public AuthCodeVo mailAuthCode(AuthCodeDto dto) {
        //生产随机验证码
        int authCodeInt = random.nextInt(10000);
        String authCode = String.format("%04d", authCodeInt);
        log.info("unionId【{}】,产生验证码【{}】", dto.getUnionId(), authCode);

        //将随机验证码存入redis
        redisUtil.set(VipCenterConstants.MAIL_AUTH_CODE +":"+dto.getMailAddress(), authCode);
        Integer exp = sysArgService.getInteger(SysArgKey.AUTH_CODE_EXP_TIME);
        redisUtil.expire(VipCenterConstants.MAIL_AUTH_CODE +":"+dto.getMailAddress(), exp, TimeUnit.MINUTES);

        MessageDto messageDto = new MessageDto();
        messageDto.setTemplateId(1L);
        messageDto.setTos(new String[]{dto.getMailAddress()});
        Map<String, String> map = new HashMap<>(1);
        map.put(VipMessageKey.AUTH_CODE, authCode);
        messageDto.setParams(map);
        vipMessageFeignClient.send(messageDto);

        return new AuthCodeVo();
    }

    /**
     * 获取用户随机码
     * @param randomCodeDto
     * @return
     */
    public RandomCodeVo randomCode(RandomCodeDto randomCodeDto) {
        TokenInfo tokenInfo = HttpServletUtil.getTokenInfo();

        UserInfo userInfo = userInfoService.getById(tokenInfo.getUserId());
        if (userInfo==null){
            log.error("用户【{}】不存在！", tokenInfo.getUserId());
            throw new ServiceException(ExceptionEnums.USER_NOT_EXIST);
        }

        //产生随机码
        RandomCodeInfo randomCodeInfo = RandomCodeInfo.builder()
                .key(snowflake.nextStringId())
                .userId(tokenInfo.getUserId())
                .randomPassword(random.nextInt(1000000)+"")
                .accessNum(0)
                .build();
        log.info("randomCodeInfo【{}】", randomCodeInfo);

        //存入redis
        redisUtil.set(VipCenterConstants.RANDOM_CODE+":"+randomCodeInfo.getKey(), JSONObject.toJSONString(randomCodeInfo));
        Integer exp = sysArgService.getInteger(SysArgKey.RANDOM_CODE_EXP_TIME);
        redisUtil.expire(VipCenterConstants.RANDOM_CODE+":"+randomCodeInfo.getKey(), exp, TimeUnit.MINUTES);

        RandomCodeVo vo = new RandomCodeVo();
        vo.setRandomCode(randomCodeInfo.getKey()+"."+randomCodeInfo.getRandomPassword());
        return vo;
    }

    /**
     * 获取用户信息
     * @param dto
     * @return
     */
    public UserInfoByCodeVo userInfoByCode(UserInfoByCodeDto dto) {
        String[] strs = dto.getRandomCode().split(VipCenterConstants.RANDOM_CODE_SPLIT);
        if (strs.length!=VipCenterConstants.RANDOM_CODE_NUM){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效随机码！");
        }

        String randomCode = strs[0];
        String randomCodePassWord = strs[1];

        String randomCodeInfoStr = redisUtil.get(VipCenterConstants.RANDOM_CODE+":"+randomCode);
        if (StringUtils.isBlank(randomCodeInfoStr)){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }
        JSONObject randomCodeInfoJson;
        try {
            randomCodeInfoJson = JSONObject.parseObject(randomCodeInfoStr);
        }catch (Exception e){
            log.error("", e);
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }
        RandomCodeInfo randomCodeInfo = JSONObject.toJavaObject(randomCodeInfoJson, RandomCodeInfo.class);
        if (StringUtils.isBlank(randomCodeInfo.getRandomPassword())){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }
        if (StringUtils.isBlank(randomCodeInfo.getUserId())){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }
        if (randomCodeInfo.getAccessNum()==null){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }
        if (StringUtils.isBlank(randomCodeInfo.getKey())){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }

        //随机码访问次数限制
        Integer randomCodeNum = sysArgService.getInteger(SysArgKey.RANDOM_CODE_NUM);
        if (randomCodeInfo.getAccessNum()>randomCodeNum){
            log.error("无效随机码！访问次数限制，已使用【{}】", randomCodeInfo.getAccessNum());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }

        //随机码访问次数加1
        randomCodeInfo.setAccessNum(randomCodeInfo.getAccessNum()+1);
        redisUtil.set(VipCenterConstants.RANDOM_CODE+":"+randomCodeInfo.getKey(), JSONObject.toJSONString(randomCodeInfo));
        Integer exp = sysArgService.getInteger(SysArgKey.RANDOM_CODE_EXP_TIME);
        redisUtil.expire(VipCenterConstants.RANDOM_CODE+":"+randomCodeInfo.getKey(), exp, TimeUnit.MINUTES);

        //随机密码检查
        if (!randomCodePassWord.equals(randomCodeInfo.getRandomPassword())){
            log.error("无效随机码！随机码【{}】", dto.getRandomCode());
            throw new ServiceException(ExceptionEnums.ERROR_PARAMS, "无效二维码，请刷新！");
        }

        UserInfo userInfo = userInfoService.getById(randomCodeInfo.getUserId());
        if (userInfo==null){
            log.error("用户【{}】不存在！", randomCodeInfo.getUserId());
            throw new ServiceException(ExceptionEnums.USER_NOT_EXIST, "用户不存在！");
        }

        UserInfoByCodeVo vo = new UserInfoByCodeVo();
        BeanUtils.copyProperties(userInfo, vo);
        return vo;
    }
}
